package com.ipay.foreign.controller;

import com.alibaba.fastjson.JSON;
import com.ipay.common.Base64Coder;
import com.ipay.entity.BizSequenceType;
import com.ipay.foreign.pojo.MerchantPayParameter;
import com.ipay.foreign.service.MerchantPayParameterService;
import com.ipay.service.impl.DefaultSequenceManager;
import com.ipay.utils.*;
import com.ipay.wechat.component.Wechat;
import com.ipay.wechat.factory.AuthorizeFactory;
import com.ipay.wechat.pojo.MerchantInfoEntity;
import com.ipay.wechat.pojo.QRCode;
import com.ipay.wechat.service.MerchantInfoService;
import com.ipay.wechat.service.PayorderService;
import com.ipay.wechat.service.QRCodeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 授权
 *
 * @author Administrator
 */
@Controller
public class AuthorizeAPIWebController {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private AuthorizeFactory auFatory;
    @Autowired
    private Wechat wechat;
    @Autowired
    private MerchantInfoService merchantInfoService;
    @Autowired
    private MerchantPayParameterService merchantPayParameterService;
    @Autowired
    private QRCodeService qRCodeService;
    /**
     * 手机端web 支付处理
     * localhost:8081/auth/payWeb?merchantNo=D2017103111000000011&codeNo=20171031205938
     */
    @RequestMapping(value = "/auth/payWebGateway", method = RequestMethod.GET)
    public ModelAndView payWebGateway(HttpServletRequest request, ModelMap modeMap){
        System.out.println("******************/auth/payWebGateway");
        String errorMesage = "";
        try {
            String sponsorOrderNo = request.getParameter("sponsorOrderNo");//发起方订单号
            String payMoney = request.getParameter("payMoney");////金额
            String codeNo = request.getParameter("codeNo");//收款员编号
            String merchantNo = request.getParameter("merchantNo");//商户编号
            String callbackUrl = request.getParameter("callbackUrl");//前台通知地址
            String notifyUrl = request.getParameter("notifyUrl");//后台通知地址（订单状态）
            String payremark = request.getParameter("payremark");////订单说明  商品描叙
            String sign = request.getParameter("sign");//签名

            if (StringUtil.isEmpty(sponsorOrderNo)) {//发起方订单号
                errorMesage = "订单号错误";
            } else if (StringUtil.isEmpty(payMoney)) {//金额
                errorMesage = "金额错误";
            } else if (StringUtil.isEmpty(codeNo)) {
                errorMesage = "收款员编号错误";
            } else if (StringUtil.isEmpty(callbackUrl)) {
                errorMesage = "前台通知地址错误";
            } else if (StringUtil.isEmpty(notifyUrl)) {
                errorMesage = "后台通知地址错误";
            } else if (StringUtil.isEmpty(sign)) {
                errorMesage = "签名错误";
            }else if (!StringUtil.isNumberToMoney(payMoney)) {
                errorMesage = "金额格式错误";
            }
            MerchantInfoEntity merchantInfo = new MerchantInfoEntity();
            if (StringUtil.isNotEmpty(merchantNo)) {
                merchantInfo = merchantInfoService.queryObject(merchantNo);
                if (merchantInfo == null) {  ///记得替换判断加密参数key是否为空
                    errorMesage = "商户信息错误";
                } else {
                    if (StringUtil.isEmpty(merchantInfo.getMerchantNo())) {
                        errorMesage = "商户信息错误";
                    } else if (StringUtil.isEmpty(merchantInfo.getPayKey())) {
                        errorMesage = "商户秘钥错误";
                    } else if (StringUtil.isNotEmpty(merchantInfo.getStatus()) && Constant.IS_VERIFY_YES.intValue() != merchantInfo.getStatus()) {//1已审核
                        if (Constant.IS_VERIFY_DJ.intValue() == merchantInfo.getStatus()) { //商户冻结
                            errorMesage = "商户已冻结";
                        } else {
                            errorMesage = "商户未审核";
                        }
                    } else if (StringUtil.isNotEmpty(merchantInfo.getDeleteStatus()) && !Constant.DELETE_STATUS_NO.equals(merchantInfo.getDeleteStatus().toString())) {//删除状态
                        errorMesage = "商户不存在";
                    }
                    if (StringUtil.isEmpty(payremark)) {
                        payremark = "付款信息来源:" + merchantInfo.getShopName() + " 的订单";
                    }
                    ///查询商户下是否包含此收款员
                    if (StringUtil.isNotEmpty(codeNo)) {
                        QRCode code = new QRCode();
                        code.setMerchantId(merchantNo);
                        code.setCodeNo(codeNo);
                        QRCode qRCode = qRCodeService.findCodeDetails(code);
                        if(qRCode!=null&&StringUtil.isNotEmpty(qRCode.getBankId())
                                &&StringUtil.isNotEmpty(qRCode.getDeleteStatus())){
                            if(!Constant.DELETE_STATUS_NO.equals(qRCode.getDeleteStatus())){//删除状态 0：未删除1：已删除
                                errorMesage = "收款码已删除";
                            }
                        }
                    }else{
                        errorMesage = "收款码对应收款员错误";
                    }
                }
            } else {
                errorMesage = "商户编号错误";
            }
            if (StringUtil.isNotEmpty(errorMesage)) {
                return new ModelAndView("pay/payError.jsp").addObject("errorMesage", errorMesage);
            }
            try {
                Map<String, String> map = new HashMap<String, String>();
                map.put("merchantNo", merchantNo);//商户编号
                map.put("codeNo", codeNo);//收款员编号
                map.put("sponsorOrderNo", sponsorOrderNo);//付款订单号
                map.put("payMoney", payMoney);//付款金额
                map.put("callbackUrl", callbackUrl);//前台通知地址
                map.put("notifyUrl", notifyUrl);//回调地址（订单状态）
                String payremarkEncode = URLEncoder.encode(payremark, "utf-8");///订单说明
                map.put("payremark", payremarkEncode);
                String strtosign = MapUtils.formatUrlMap(map, false, false);
                //TODO 查询商户相关数据  =payKey
                String parameter = Base64Coder.encode(strtosign);
                String signstr = MD5.sign(parameter, "&payKey=" + merchantInfo.getPayKey(), "utf-8");
                if (StringUtil.isNotEmpty(sign) && sign.equals(signstr)) {
                    modeMap.put("sponsorOrderNo", sponsorOrderNo);//订单号
                    modeMap.put("payMoney", payMoney);//订单金额
                    modeMap.put("callback_url", callbackUrl);///前段回调地址
                    modeMap.put("payremark", payremark);///订单说明
                    modeMap.put("shopName", merchantInfo.getShopName());///店铺名称
                    modeMap.put("codeNo", codeNo);///店铺名称
                    ///保存请求数据
                    MerchantPayParameter merchantPay = new MerchantPayParameter();
                    merchantPay.setSponsorOrderNo(sponsorOrderNo);
                    merchantPay.setCodeNo(codeNo);
                    merchantPay.setMerchantNo(merchantNo);
                    merchantPay.setPayMoney(new BigDecimal(payMoney));
                    merchantPay.setCallbackUrl(callbackUrl);
                    merchantPay.setNotifyUrl(notifyUrl);
                    merchantPay.setPayremark(payremark);
                    merchantPay.setSign(signstr);
                    merchantPay.setStart(Constant.START_WZF);//发起 订单状态（0未支付，1支付中，2已支付，3已取消）
                    merchantPay.setTypes(Constant.TYPES_DSFPC);//发起类型（0第三方pc端，1收款员生成固额二维码）
                    if(merchantPay.getPayMoney().compareTo(new BigDecimal(0)) == 1){//结果是:-1 小于,0 等于,1 大于
                        merchantPayParameterService.save(merchantPay);
                        logger.info("===========id:" + merchantPay.getId());
                        modeMap.put("payId", merchantPay.getId());////商户编号
                        modeMap.put("sign", signstr);////签名

                        System.out.println("******************/auth/payWebGateway"+merchantPay.getId());

                        String params = "?payId=" + merchantPay.getId() + "&sign=" + sign + "&merchantNo=" + merchantNo + "&codeNo=" + codeNo;
                        String ua = request.getHeader("User-Agent");
                        String post_url = "";
                        logger.info("***********ua------------" + params);
                        logger.info("***********ua------------" + ua);
                        if (ua.indexOf("MicroMessenger") > 0) {// 微信
                            post_url = auFatory.dealAuthorize("payViewWebGateway", params);
                        } else if (ua.indexOf("AlipayClient") > 0) {// 支付宝
                            post_url = auFatory.createAliPostUrl("payViewWebGateway", params);
                        } else {
                            return new ModelAndView("pay/payError.jsp").addObject("errorMesage", "暂时我们只开通了微信，支付宝支付功能！后续我们会相继开通其它支付渠道");
                        }
                        logger.info("***********post_url------------" + post_url);
                        logger.info("###########post_url------------" + post_url);
                        return new ModelAndView("redirect:" + post_url);
                        //return new ModelAndView("pay/payViewWebGateway.jsp");
                    }else{
                        errorMesage="金额错误";
                    }
                } else {
                    errorMesage="签名信息错误";
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                logger.info("订单说明转utf-8码错误");
                errorMesage="参数错误";
            } catch (Exception e) {
                e.printStackTrace();
                errorMesage="参数错误";
                logger.info("Base64Coder处理数据错误");
            }
        }catch (Exception e){
            e.printStackTrace();
            errorMesage="系统异常，请联系管理员";
        }
        return new ModelAndView("pay/payError.jsp").addObject("errorMesage", errorMesage);
    }

    /**第三方发起支付请求 与/merchant/payGateway 是一起的
     * @param merchantNo         商户号
     * @param codeNo             收款码编号
     * @param request
     * @param redirectAttributes
     */
    @RequestMapping(value = "/auth/payViewWebGateway", method = RequestMethod.GET)
    public ModelAndView payViewWebGateway(@RequestParam String merchantNo, @RequestParam String codeNo, HttpServletRequest request,
                                          final RedirectAttributes redirectAttributes) throws Exception {
        System.out.println("******************/auth/payViewWebGateway");
        String ua = request.getHeader("User-Agent");
        if (ua.indexOf("MicroMessenger") > 0) {// 微信
            redirectAttributes.addAttribute("User-Agent", "MicroMessenger");
        } else if (ua.indexOf("AlipayClient") > 0) {// 支付宝
            redirectAttributes.addAttribute("User-Agent", "AlipayClient");
        } else {
            return new ModelAndView("pay/payError.jsp").addObject("errorMesage", "暂时我们只开通了微信，支付宝支付功能！后续我们会相继开通其它支付渠道");
        }
        logger.info("merchantNo-----" + merchantNo + "baseUrl-----" + wechat.getBaseUrl());
        Map<String, String> map = new HashMap<String, String>();
        String payId = request.getParameter("payId");//支付参数id
        String sign = request.getParameter("sign");//签名+key
        MerchantPayParameter merchantPayParameter = merchantPayParameterService.queryObject(payId);
        if (merchantPayParameter == null || StringUtil.isEmpty(merchantPayParameter.getMerchantNo())) {
            return new ModelAndView("pay/payError.jsp").addObject("errorMesage", "订单信息错误");
        }
        MerchantInfoEntity merchantInfo = merchantInfoService.queryObject(merchantPayParameter.getMerchantNo());
        if (merchantInfo == null || StringUtil.isEmpty(merchantInfo.getMerchantNo()) || StringUtil.isEmpty(merchantInfo.getPayKey())) {  ///记得替换判断加密参数key是否为空
            return new ModelAndView("pay/payError.jsp").addObject("errorMesage", "商户信息错误");
        }
        map.put("merchantNo", merchantPayParameter.getMerchantNo());
        map.put("codeNo", merchantPayParameter.getCodeNo());
        map.put("sponsorOrderNo", merchantPayParameter.getSponsorOrderNo());
        map.put("payMoney", String.valueOf(merchantPayParameter.getPayMoney()));
        String payremarkEncode = URLEncoder.encode(merchantPayParameter.getPayremark(), "utf-8");///订单说明
        map.put("payremark", payremarkEncode);
        map.put("callbackUrl", merchantPayParameter.getCallbackUrl());
        map.put("notifyUrl", merchantPayParameter.getNotifyUrl());
        //参数ascii码从小到大排序后转QueryString的格式
        String strtosign = MapUtils.formatUrlMap(map, false, false);
        //参数Base64Coder处理
        String parameter = Base64Coder.encode(strtosign);
        //数据MD5加密生成签名
        String signstr = MD5.sign(parameter, "&payKey=" + merchantInfo.getPayKey(), "utf-8");
        logger.info("=======================signstr:" + signstr + "   =   sign:" + sign + "   =   " + (signstr.equals(sign)));
        if (!signstr.equals(sign)) { //签名对比
            return new ModelAndView("pay/payError.jsp").addObject("errorMesage", "签名错误");
        }
        redirectAttributes.addAttribute("sponsorOrderNo", merchantPayParameter.getSponsorOrderNo());//发起方订单号
        redirectAttributes.addAttribute("payMoney", merchantPayParameter.getPayMoney());////付款金额
        redirectAttributes.addAttribute("payremark", payremarkEncode);//订单说明
        redirectAttributes.addAttribute("notifyUrl", merchantPayParameter.getNotifyUrl());//回调地址
        redirectAttributes.addAttribute("sign", sign);//签名+key
        redirectAttributes.addAttribute("payId", payId);//支付参数id
        redirectAttributes.addAttribute("codeNo", codeNo);//收款员编号
        redirectAttributes.addAttribute("merchantId", merchantNo);//商家编号
        redirectAttributes.addAttribute("openid", request.getSession().getAttribute("openid"));//用户唯一标示
        request.setCharacterEncoding("utf-8");
        String shopName = "";
        if (StringUtil.isNotEmpty(merchantInfo.getShopName())) {
            shopName = URLEncoder.encode(merchantInfo.getShopName(), "utf-8");
        }
        logger.info("shopName----" + shopName + "-----logo-----" + merchantInfo.getLogo());
        redirectAttributes.addAttribute("logo", merchantInfo.getLogo());
        redirectAttributes.addAttribute("shopName", shopName);
        redirectAttributes.addAttribute("baseUrl", wechat.getBaseUrl());
        redirectAttributes.addAttribute("baseUrlWechat", wechat.getBaseUrlWechat());
        //return new ModelAndView("redirect:" + wechat.getBaseUrl() + "pay/pay.html");
        return new ModelAndView("redirect:" + wechat.getBaseUrlWechat() + "payViewWebGateway.html");
    }

    //================================================
    //================================================
    //================================================
    //================================================
    /**
     * pc测试方法
     * 测试服务器地址  www.iknowtec.net
     * https://www.***.cn/wechat/auth/payWeb?merchantNo=D2017103111000000011&codeNo=20171031205938
     */
    @RequestMapping(value = "/auth/payWeb", method = RequestMethod.GET)
    public ModelAndView payWeb(@RequestParam String merchantNo, @RequestParam String codeNo) throws Exception {
        MerchantInfoEntity merchantInfo = merchantInfoService.queryObject(merchantNo);
        if (merchantInfo == null || StringUtil.isEmpty(merchantInfo.getMerchantNo()) || StringUtil.isEmpty(merchantInfo.getPayKey())) {  ///记得替换判断加密参数key是否为空
            return new ModelAndView("pay/payError.jsp").addObject("errorMesage", "商户信息错误");
        }
        String sponsorOrderNo = DefaultSequenceManager.get().next(BizSequenceType.TRANSQ);//订单号
        logger.info("==/auth/payWeb=付款订单号====sponsorOrderNo:" + sponsorOrderNo);
        String notifyUrl = "https://www.***.cn/pay-manager/bankInfo/doCallbackNotify";
        Map<String, String> map = new HashMap<String, String>();
        map.put("merchantNo", merchantNo);//商户编号
        map.put("codeNo", codeNo);//收款员编号
        map.put("sponsorOrderNo", sponsorOrderNo);//付款订单号
        map.put("payMoney", "0.01");//付款金额
        map.put("callbackUrl", wechat.getBaseUrl()+"auth/isMerchant");//前台通知地址
        map.put("notifyUrl", notifyUrl);//回调地址（订单状态）
        String payremark = URLEncoder.encode("国外旅泰国旅游保险", "utf-8");///订单说明
        map.put("payremark", payremark);

        System.out.println("wxJsPay====:" + JSON.toJSONString(map));
        String strtosign = MapUtils.formatUrlMap(map, false, false);
        //TODO 查询商户相关数据
        String parameter = Base64Coder.encode(strtosign);
        String signstr = MD5.sign(parameter, "&payKey=" + merchantInfo.getPayKey(), "utf-8");
        System.out.println("=====/auth/payWeb=====signstr===========:" + signstr);
        map.put("sign", signstr);
        String param = strtosign + "&sign=" + signstr;
        System.out.println("====/auth/payWeb======param===========:" + param);
        String redirectUrl = wechat.getBaseUrl() + "auth/payWebGateway?" + param;//正式使用
        System.out.println("******/auth/payWeb****************"+redirectUrl);
        //String redirectUrl = "http://localhost:8081/auth/payWebGateway?" + param;//测试使用
        return new ModelAndView("redirect:" + redirectUrl);
    }
}